package zack.gateway.core.session;

import zack.gateway.core.authorization.IAuth;
import zack.gateway.core.authorization.auth.AuthService;
import zack.gateway.core.bind.IGenericReference;
import zack.gateway.core.bind.MapperRegistry;
import zack.gateway.core.datasource.Connection;
import zack.gateway.core.executor.Executor;
import zack.gateway.core.executor.SimpleExecutor;
import zack.gateway.core.mapping.HttpStatement;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.ReferenceConfig;
import org.apache.dubbo.config.RegistryConfig;
import org.apache.dubbo.rpc.service.GenericService;

import java.util.HashMap;
import java.util.Map;

/**会话生命周期配置
 * @author A1793
 */
public class Configuration {

    private  String host = "127.0.0.1";
    private  int port = 7397;

    private  int bossGroupSize = 1;
    private  int workerGroupSize = 4;
    //泛化调用注册机
    private final MapperRegistry mapperRegistry = new MapperRegistry(this);
    //鉴权配置
    private final IAuth authService = new AuthService();
    //存储压迫进行泛化调用的网关信息
    private final Map<String, HttpStatement> httpStatements = new HashMap<>();
    //当前工程的应用配置
    private final Map<String, ApplicationConfig> applicationConfigMap = new HashMap<>();
    //要访问的服务所在的注册中心的配置
    private final Map<String, RegistryConfig> registryConfigMap = new HashMap<>();
    //要调用的接口配置
    private final Map<String, ReferenceConfig<GenericService>> referenceConfigMap = new HashMap<>();

    public String getHost() {
        return host;
    }

    public int getPort() {
        return port;
    }

    public int getBossGroupSize() {
        return bossGroupSize;
    }

    public int getWorkerGroupSize() {
        return workerGroupSize;
    }

    public void setHost(String host) {
        this.host = host;
    }

    public void setPort(int port) {
        this.port = port;
    }

    public void setBossGroupSize(int bossGroupSize) {
        this.bossGroupSize = bossGroupSize;
    }

    public void setWorkerGroupSize(int workerGroupSize) {
        this.workerGroupSize = workerGroupSize;
    }

    public Configuration() {
//        // ApplicationConfig：当前应用（网关）的身份配置，用于定义当前应用（这里指网关）的基本信息，告诉 Dubbo 框架 “我是谁”。
//        //代码中配置了
//        //application.setName("api-gateway-test")：
//        // 设置当前应用的名称为 api-gateway-test（相当于网关的 “身份证”，Dubbo 会用这个名称在注册中心标识当前应用）。
//        //application.setQosEnable(false)：
//        // 关闭 Dubbo 的 QoS（Quality of Service，服务治理）功能（QoS 用于远程管理服务，网关作为调用方可能不需要开启）。
//        ApplicationConfig application = new ApplicationConfig();
//        application.setName("api-gateway-test");
//        application.setQosEnable(false);
//        //RegistryConfig：注册中心配置，用于定义远程服务的注册中心信息，告诉 Dubbo 框架 “去哪里找远程服务”。
//        //代码中配置了：
//        //registry.setAddress("zookeeper://127.0.0.1:2181")：
//        // 设置注册中心的地址为本地 ZooKeeper 服务（127.0.0.1:2181）。Dubbo 通常依赖 ZooKeeper 作为注册中心，存储服务提供者的地址信息。
//        //registry.setRegister(false)：
//        // 设置当前应用（网关）“不注册自己” 到注册中心。因为网关是服务消费者（只调用其他服务，不提供服务），所以不需要把自己注册到注册中心。
//        //作用：网关通过这个配置连接注册中心，从而发现并获取远程服务（如 IActivityBooth）的提供者地址。
//        RegistryConfig registry = new RegistryConfig();
//        registry.setAddress("zookeeper://122.51.38.***:2181?timeout=600000");
//        registry.setRegister(false);
//        //ReferenceConfig<GenericService>：远程服务的引用配置，用于定义要调用的远程服务的具体信息，告诉 Dubbo 框架 “我要调用哪个服务”。
//        //代码中配置了：
//        //reference.setInterface("cn.bugstack.gateway.rpc.IActivityBooth")：
//        // 指定要调用的远程服务接口的全类名（即远程服务的 “唯一标识”，Dubbo 通过接口名找到对应的服务）。
//        //reference.setVersion("1.0.0")：
//        // 指定要调用的服务版本（同一个接口可能有多个版本，通过版本号区分，避免冲突）。
//        //reference.setGeneric("true")：
//        // 开启泛化调用模式（GenericService 是 Dubbo 泛化调用的接口）。
//        // 泛化调用允许在不依赖远程服务接口类（即不需要引入 IActivityBooth.class 文件）的情况下调用服务，
//        // 这对网关非常重要（网关不需要依赖所有服务的接口包）。
//        //作用：这是网关调用远程服务的 “直接配置”，Dubbo 根据这些信息生成服务代理，让网关可以通过 GenericService 接口调用远程服务的方法。
//        ReferenceConfig<GenericService> reference = new ReferenceConfig<>();
//        reference.setInterface("cn.bugstack.gateway.rpc.IActivityBooth");
//        reference.setVersion("1.0.0");
//        reference.setGeneric("true");
//
//        applicationConfigMap.put("api-gateway-test", application);
//        registryConfigMap.put("api-gateway-test", registry);
//        referenceConfigMap.put("cn.bugstack.gateway.rpc.IActivityBooth", reference);

    }
    public synchronized void registryConfig(String applicationName, String address, String interfaceName, String version) {
        if (applicationConfigMap.get(applicationName) == null) {
            ApplicationConfig application = new ApplicationConfig();
            application.setName(applicationName);
            application.setQosEnable(false);
            applicationConfigMap.put(applicationName, application);
        }

        if (registryConfigMap.get(applicationName) == null) {
            RegistryConfig registry = new RegistryConfig();
            registry.setAddress(address);
            registry.setRegister(false);
            registryConfigMap.put(applicationName, registry);
        }

        if (referenceConfigMap.get(interfaceName) == null) {
            ReferenceConfig<GenericService> reference = new ReferenceConfig<>();
            reference.setInterface(interfaceName);
            reference.setVersion(version);
            reference.setGeneric("true");
            referenceConfigMap.put(interfaceName, reference);
        }
    }

    public ApplicationConfig getApplicationConfig(String applicationName) {
        return applicationConfigMap.get(applicationName);
    }

    public RegistryConfig getRegistryConfig(String applicationName) {
        return registryConfigMap.get(applicationName);
    }

    public ReferenceConfig<GenericService> getReferenceConfig(String interfaceName) {
        return referenceConfigMap.get(interfaceName);
    }

    public void addMapper(HttpStatement httpStatement) {
        mapperRegistry.addMapper(httpStatement);
    }
    public IGenericReference getMapper(String uri,GatewaySession gatewaySession) {
        return mapperRegistry.getMapper(uri,gatewaySession);
    }
    public void addHttpStatement(HttpStatement httpStatement) {
        httpStatements.put(httpStatement.getUri(), httpStatement);
    }

    public HttpStatement getHttpStatement(String uri) {
        return httpStatements.get(uri);
    }
    public Executor newExecutor(Connection connection){
        return new SimpleExecutor(connection,this);
    }
    public boolean authValidate(String uid,String token ) {
        return authService.validate(uid,token);
    }
}
